#include "usb_command.h"

#include "main.h"
#include "USB_API.h"
#include "c8051F320.h"
#include "USB_BL_APP_Shared.h"
#include "adc.h"

bit			tx_enable	= 0;
UINT			bytes_sent	= 0x0000;
UINT			bytes_received	= 0x0000;
BYTE xdata		buffer[BUFFER_SIZE]; // _at_ 0x0000;
BYTE xdata 		*ptr_Cap;			// puntero a byte de buffer de captura, manejado x la captura
BYTE xdata 		*ptr_Tx;				// ptr a byte de buffer de captura, manejado x la transmisi'on
								// overrun si y solo s'i bytes_a_tx>BUFFER_SIZE
BYTE xdata 		Out_Packet[PACKET_SIZE] = {0,0,0,0,0,0,0,0};   // Last packet received from host
BYTE xdata 		In_Packet[PACKET_SIZE]  = {0,0,0,0,0,0,0,0};   // Next packet to sent to host

//-----------------------------------------------------------------------------
// USBXpress API ISR
//	ISR that handles interrupts generated by the USBXpress API
//-----------------------------------------------------------------------------
void USB_API_ISR (void) interrupt 16
{
	BYTE INTVAL = Get_Interrupt_Source();

	if (INTVAL & TX_COMPLETE) {
		switch(estado) {
		case ST_BOOTLOADER:
			EA = 0;           	// Dishabilito todas las interrupciones
			BOOTLOAD_REQ();   	// Invoco al bootloader.
			break;
		case ST_ACK_COMM:
			estado=ST_IDLE;
			break;
		}
	}
	if (INTVAL & RX_COMPLETE) {
		if (estado == ST_TEST) {
			estado = ST_TEST;
		} else if (estado == ST_CAPTURE) {
			// Si es ack de transmisi'on, descontar a ptr_Tx los bytes reccibidos
			Block_Read(Out_Packet, PACKET_SIZE);       // Read the received PACKZET_SIZE packet
			if (Out_Packet[0] == COMM_ACK_TX) {
				bytes_received=256*Out_Packet[1]+Out_Packet[2];
				// ptr_Cap-=bytes_received;
				// ptr_Tx-=bytes_received;
				// bytes_sent-=bytes_received;
				// tx_enable=1;
			} else {
				estado=ST_ACK_COMM;
			}
		} else {
			estado=ST_ACK_COMM;
		}
	}
	if (INTVAL & DEV_SUSPEND) {
      		Suspend_Device();
      	}
	if (INTVAL & DEVICE_OPEN) {		// Received when a device handle is opened by PC App
      		TR1     = 1;			// Start Timer1
      	}
	if (INTVAL & DEVICE_CLOSE) {		// Received when a device handle is closed by PC App
      		TR1     = 0;			// Stop Timer1
      	}

	if (estado == ST_ACK_COMM) {
		responder_comandos();
	}
}

void responder_comandos (void)
{
	// Se recibio un comando que debe ser confirmado.
	// Leo el paquete de datos con el comando y sus parametros
	// Es parte de un ISR, por lo que deberia ser minimo

	Block_Read(Out_Packet, PACKET_SIZE);
	switch(Out_Packet[0]) 		// Segun el comando, hago:
	{			 
	case COMM_BOOTLOAD_REQ:
		estado=ST_BOOTLOADER;
		In_Packet[0]= COMM_BOOTLOAD_REQ^0xFF;	// Ack del commando
		Block_Write(In_Packet, 1);
		break;

	case COMM_GET_CLOCK:
		In_Packet[0]= COMM_GET_CLOCK^0xFF;	// Ack del commando
		In_Packet[1]= OSCICN;		   		// 0XC0  clock SYSCLK / 8
		In_Packet[2]= CLKSEL;				// 0X00 = USB X 4 , SYSCLK interno
		Block_Write(In_Packet, 3);
		break;

	case COMM_LED_ON:
		led_status=LED_ON;						// TEST LED blinking
		In_Packet[0]= COMM_LED_ON^0xFF;			// Ack del commando
		Block_Write(In_Packet, 1);
		break;

	case COMM_LED_OFF:
		led_status=LED_OFF;
		In_Packet[0]= COMM_LED_OFF^0xFF;
		Block_Write(In_Packet, 1);
		break;

	case COMM_LED_BLINK:
		led_status=LED_BLINK;
		In_Packet[0]= COMM_LED_BLINK^0xFF;
		Block_Write(In_Packet, 1);
		break;

	case COMM_ADC_START:
		In_Packet[0] = COMM_ADC_START ^ 0xFF;
		Block_Write(In_Packet, 1);
		adc_start();
		break;

	case COMM_ADC_STOP:
		// In_Packet[0] = COMM_ADC_STOP ^ 0xFF;
		// Block_Write(In_Packet, 1);
		adc_stop();
		break;

	default:
		if (raw_buffer_next == RAW_BUFFER_SIZE) {
			Block_Write(raw_buffer, sizeof(raw_buffer));
			raw_buffer_next = 0;
		}
		break;
	}
}

//-----------------------------------------------------------------------------
// Suspend_Device
// Called when a DEV_SUSPEND interrupt is received.
// - Disables all unnecessary peripherals
// - Calls USB_Suspend()
// - Enables peripherals once device leaves suspend state
//-----------------------------------------------------------------------------
void Suspend_Device (void)
{
	bit TestLed_save = TestLed;
	// bit Timer2_status = TR2;
   																	
	// Disable peripherals before calling USB_Suspend()
	TestLed = 1;
	// TR2 = 0;

	USB_Suspend(); // Pongo el dispositivo "suspend state"

	// Once execution returns from USB_Suspend(), device leaves suspend state.
	// Reenable peripherals

	// TR2 = Timer2_status;	// Timer 2 reestablecido
	TestLed = TestLed_save; // Reestablezco Led
}

